package com.runjian.rundo.iot.agent.business.publisher.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import com.runjian.rundo.bmp.kernel.common.spring.context.utils.MdcUtils;
import com.runjian.rundo.bmp.kernel.common.spring.context.utils.SpringUtils;
import com.runjian.rundo.iot.agent.business.publisher.DeviceMessageProcessor;
import com.runjian.rundo.iot.agent.business.publisher.DeviceMessagePublisher;
import com.runjian.rundo.iot.agent.common.enums.DeviceMessageType;
import com.runjian.rundo.iot.agent.common.message.DeviceMessage;

import lombok.extern.slf4j.Slf4j;

/**
 * 设备消息发送到IoT平台端的发送器 默认实现
 *
 * @author LiGang
 */
@Slf4j
@Component
@SuppressWarnings({"rawtypes", "unchecked"})
public class DefaultDeviceMessagePublisher implements DeviceMessagePublisher {

    private final Map<DeviceMessageType, DeviceMessageProcessor> strategyMap = new ConcurrentHashMap<>();

    /**
     * 对象初始化：缓存起来设备消息处理器，每种类型对应的处理器
     */
    @PostConstruct
    public void init() {
        Map<String, DeviceMessageProcessor> deviceMessageProcessorMap = SpringUtils.getBeans(DeviceMessageProcessor.class);
	    for (Map.Entry<String, DeviceMessageProcessor> entry : deviceMessageProcessorMap.entrySet()) {
		    String name = entry.getKey();
		    DeviceMessageProcessor processor = entry.getValue();
            DeviceMessageType type = processor.getType();
            log.info("[DefaultDeviceMessagePublisher] 加载设备消息处理器成功: process.type = {}, processName = {}", processor.getType(), name);
		    strategyMap.put(type, processor);
	    }
    }

    @Override
    public boolean publish(DeviceMessage deviceMessage) {
        MdcUtils.setTraceIdIfAbsent();
        DeviceMessageProcessor deviceMessageProcessor = strategyMap.get(deviceMessage.getType());
        if (deviceMessageProcessor == null) {
            log.warn("未定义当前消息类型处理器：messageType = {}", deviceMessage.getType().getText());
            return false;
        }
        deviceMessageProcessor.process(deviceMessage);
        return true;
    }
}
